﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;

namespace AspNetMVCSourceTextDiffCompare.Utilities
{
    public static class XmlUtilities
    {
        public static bool ValidateXml(Stream fileContent, XmlSchema xmlSchema, out ValidationEventArgs[] xmlError)
        {
            xmlError = null;
            try
            {
                XDocument doc = XDocument.Load(fileContent);
                return ValidateXml(doc, xmlSchema, out xmlError);
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool ValidateXml(Stream fileContent, XmlSchema xmlSchema, out XDocument resultXml, out ValidationEventArgs[] xmlErrors)
        {
            xmlErrors = null;
            resultXml = null;
            try
            {
                XDocument doc = XDocument.Load(fileContent);
                resultXml = doc;
                return ValidateXml(doc, xmlSchema, out xmlErrors);
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool ValidateXml(XDocument xDocument, XmlSchema xmlSchema, out ValidationEventArgs[] xmlErrors)
        {
            bool result = true;
            List<ValidationEventArgs> xmlErrorsList = new List<ValidationEventArgs>();
            try
            {
                var doc = xDocument;
                var schemas = new XmlSchemaSet();
                schemas.Add(xmlSchema);
                ValidationEventHandler validationEventHandler = (o, e) => { xmlErrorsList.Add(e); result = false; };

                result = doc.Root != null && doc.Root.Name.Namespace == xmlSchema.TargetNamespace;
                if (!result)
                    return result;

                doc.Validate(schemas, validationEventHandler);
            }
            catch (Exception ex)
            {
                return false;
            }
            finally
            {
                xmlErrors = xmlErrorsList.ToArray();
            }

            return result;
        }

        public static XmlDocument ToXmlDocument(this XDocument xDocument)
        {
            var xmlDocument = new XmlDocument();
            using (var xmlReader = xDocument.CreateReader())
            {
                xmlDocument.Load(xmlReader);
            }
            return xmlDocument;
        }

        public static XDocument ToXDocument(this XmlDocument xmlDocument)
        {
            using (var nodeReader = new XmlNodeReader(xmlDocument))
            {
                nodeReader.MoveToContent();
                return XDocument.Load(nodeReader);
            }
        }
    }

    public static class XmlDocumentExtension
    {
        public static bool TryParseXml(this XmlDocument value, string xml)
        {
            try
            {
                value.LoadXml(xml);
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception("Xml is invalid, details:" + ex.Message);
            }
        }
    }
}